package com.atguigu.java;

import org.junit.Test;

import java.io.*;
import java.util.Date;

/**
 * @author yihu
 * @create 2021-05-29 17:13
 * @email:1057202547@qq.com
 * @dec:
 *  一、流的分类：
 *  * 1.操作数据单位：字节流、字符流
 *  * 2.数据的流向：输入流、输出流
 *  * 3.流的角色：节点流、处理流
 *  *
 *  * 二、流的体系结构
 *  * 抽象基类                     节点流（或文件流）                               缓冲流（处理流的一种）
 *  * InputStream(字节输入流)       FileInputStream   (read(byte[] buffer))        BufferedInputStream (read(byte[] buffer))
 *  * OutputStream(字节输出流)      FileOutputStream  (write(byte[] buffer,0,len)  BufferedOutputStream (write(byte[] buffer,0,len) / flush()
 *  * Reader(字符输入流)            FileReader (read(char[] cbuf))                 BufferedReader (read(char[] cbuf) / readLine())
 *  * Writer (字符输出流)           FileWriter (write(char[] cbuf,0,len)           BufferedWriter (write(char[] cbuf,0,len) / flush()
 *
 *  具体操作
 *    ① 实例化file对象
 *    ② 流的实例化
 *    ③ 读入的操作
 *    ④ 关闭流
 *
 */
public class FileReadWriterTest {
    /**
     * 将day09下的hello.txt文件内容读入程序中，并输出到控制台
     *
     *  说明点：
     *     1. read()的理解：返回读入的一个字符。如果达到文件末尾，返回-1
     *     2. 异常的处理：为了保证流资源一定可以执行关闭操作。需要使用try-catch-finally处理
     *     3. 读入的文件一定要存在，否则就会报FileNotFoundException。
     * @param
     */
    @Test
    public void testFileReader() {
        FileReader fr = null;
        try {
            //相对于当前Module下的路径
            //① 实例化file对象
            File file = new File("hello.txt");
            //②提供具体的流 ---字符输入流 (将文件读到程序中，对于程序来说就是输入的过程)
            fr = new FileReader(file);//文件没有时 这里会报FileNotFoundException 异常
            //③将数据的从内存中通过流读出来
            //返回读入的一个字符，如果达到文件的末尾了，返回-1
            //        int data = fr.read();
            //        while (data!=-1){
            //            System.out.println((char) data);
            //            data = fr.read();
            //        }
            int data;
            while ((data = fr.read())!=-1){
                System.out.println((char) data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //④关闭流
            try {
                if(fr!=null){
                    fr.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    //对read()操作升级：使用read的重载方法
    @Test
    public void testFileReader1()  {
        FileReader fr = null;
        try {
            //① 实例化file对象-->
            File file = new File("hello.txt");
            //② 流的实例化 （将文件输入到内存中）将file写入到内存中
            fr = new FileReader(file);
            //③ 读入的操作
            int data;
            //fr.read(cbuffer)  返回每次读入到cbuf数组中的字符的个数。如果达到文件末尾，返回-1
            char[] cbuffer = new char[5];
            int len; //每次读进到cbuffer 的具体个数(真实个数)
            while ((len = fr.read(cbuffer))!=-1){
                //错误的写法  cbuffer 这个数组中最后可能没有写入5个，由前一次替代了几个，
//                for (int i=0;i<cbuffer.length;i++){
//                    System.out.print(cbuffer[i]);
//                }
//                System.out.println("--------");
                  //正确的方式一
//                for (int i =0;i < len;i++){
//                    System.out.print(cbuffer[i]);
//                }
                  //正确的方式二  //String str = new String(cbuffer);//错误：cbuffer 这个数组中最后可能没有写入5个，由前一次替代了几个，
                  String str = new String(cbuffer,0,len);
                  System.out.print(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //④关闭流
            try {
                if(fr!=null){
                    fr.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 从内存中写出数据到硬盘的文件里
     * 说明：
     *     1. 输出操作，对应的File可以不存在的。并不会报异常
     *     2.
     *          File对应的硬盘中的文件如果不存在，在输出的过程中，会自动创建此文件。
     *          File对应的硬盘中的文件如果存在：
     *                 如果流使用的构造器是：FileWriter(file,false) / FileWriter(file):对原有文件的覆盖
     *                 如果流使用的构造器是：FileWriter(file,true):不会对原有文件覆盖，而是在原有文件基础上追加内容
     */
    @Test
    public  void  testFileWriter() {
        FileWriter fw = null;
        try {
            //①提供到file类的对象，指明写出到的文件
            File file = new File("hello1.tx");

            //②提供fileWriter的对象，用于数据的输出
            fw = new FileWriter(file);

            //③写数据
            fw.write("I have a dream\n");
            fw.write("you need to  have a dream");

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
           if(fw!=null){
               //④关闭流
               try {
                   fw.close();
               } catch (IOException e) {
                   e.printStackTrace();
               }
           }
        }
    }

    /**
     * 将文件先读取出来到内存中，在写入另一个文件
     */
    @Test
    public void testFileReaderFileWriter() {
        FileReader fr = null;
        FileWriter fw = null;
        try {
            //①创建File类的对象，指明读入和写出的文件
            File srcFile = new File("hello.txt");
            File destFile = new File("hello2.txt");

            //不能使用字符流来处理图片等字节数据
            //File srcFile = new File("爱情与友情.jpg");
            //File destFile = new File("爱情与友情1.jpg");

            //创建一个输入流将srcFile文件输入到流中  创建一个输出流到destFile
            fr = new FileReader(srcFile);
            fw = new FileWriter(destFile);

            //3.数据的读入和写出操作
            char[] cbuf = new char[10];
            int len =-1; //fr.read 记录每次读入到cbuf数组中的字符的个数
            while ((len = fr.read(cbuf))!=-1){
                fw.write(cbuf,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(fr!=null){
                //关闭流
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(fw!=null){
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }




    public static void main(String[] args) {
        //File file = new File("hello.txt");
        //System.out.println(file.getAbsolutePath());//D:\java_study\java_ideawokespace\JavaSenior\hello.txt
        //相对于当前工程
        File file = new File("day09\\hello.txt");
    }

}
